#ifndef		SPIRIT_H
#define		SPIRIT_H

#include <Ogre.h>
#include <OIS/OIS.h>
#include "TerrainEx.h"

using namespace Ogre;

#define CHAR_HEIGHT 5          // height of character's center of mass above ground
#define NUM_ANIMS 13           // number of animations the character has
#define ANIM_FADE_SPEED 1.5f   // animation crossfade speed in % of full weight per second
#define JUMP_ACCEL 30.0f 
#define	GRAVITY		120.0f
#define FRAMESCALE	0.01f


class Spirit
{
private:

	enum AnimID
	{
		ANIM_IDLE_BASE,
		ANIM_IDLE_TOP,
		ANIM_RUN_BASE,
		ANIM_RUN_TOP,
		ANIM_HANDS_CLOSED,
		ANIM_HANDS_RELAXED,
		ANIM_DRAW_SWORDS,
		ANIM_SLICE_VERTICAL,
		ANIM_SLICE_HORIZONTAL,
		ANIM_DANCE,
		ANIM_JUMP_START,
		ANIM_JUMP_LOOP,
		ANIM_JUMP_END,
		ANIM_NONE
	};

	SceneManager*				m_pSceneMgr;
	Camera*						m_pCamera;
	TerrainEx*					m_pterrain;
	SceneNode*					m_pBodyNode;
	SceneNode*					m_pBodyNodeHelp;
	SceneNode*					m_pBodyNodeCollision;

	Entity*						m_pBodyEnt;
	Entity*						m_pBodyEntHelp;
	Entity*						m_pBodyCollision;
	Entity*						m_pSword1;
	Entity*						m_pSword2;
	
	RibbonTrail*				m_pSwordTrail;
	AnimationState*				m_pAnims[NUM_ANIMS];			// master animation list
	bool						m_bFadingIn[NUM_ANIMS];            // which animations are fading in
	bool						m_bFadingOut[NUM_ANIMS];           // which animations are fading out
	AnimID						m_aBaseAnimID;					// current base (full- or lower-body) animation
	AnimID						m_aTopAnimID;						// current top (upper-body) animation
	Real						m_rTimer;							// general timer to see how long animations have been playing
	Real						mVerticalVelocity;  
	size_t						m_fControlModel;						// control model 0 key , 1 mouse

	// key 
	Vector3						m_vKeyDirection; 
	Vector3						m_vGoalDirection;     // actual intended direction in world-space
	// move attribute
	bool						m_bWalked ;
	float						m_fWalkingSpeed;
	float						m_fWalkingScale;
	Ogre::Vector3				m_vInitPos;
	Ogre::Vector3				m_vEntityTranslate;
	Ogre::Vector3				m_vEntityTarget;
	Ogre::Vector3				m_vEntityCurrentPos;
	Ogre::Vector3				m_vEntityCurrentTarget;
	float						m_fDistance;
	bool						m_bSwordsDrawn;
	float						m_fAttack;

	std::vector<SpiritCollision>		m_vAxisaligneboxList;
	std::vector<std::string>			m_vAvoidColliSionName;

	Real						m_frameEvent;

private:
	static int						m_nCount;
protected:
	void	setBaseAnimation(AnimID id, bool result = false);
	void	setTopAnimation(AnimID id, bool reset = false);

	void	fadeAnimations(Real deltaTime);
	void	clickTarget(Vector3 mtarget);
	void	updateAnimations(Real deltaTime);
	void	setupAnimations();
	void	chackTargetPosition(bool conf =false, Vector3& vec = Vector3(Vector3::ZERO));
	void	collisionObject(Ogre::AxisAlignedBox box);
	void	forEachAxisalignebox();
	
public:

	Spirit(SceneManager* mscenemgr, Camera* camera, TerrainEx*	terrain);
	~Spirit();
	void	createSpirit();
	void	updateSpirit(const Ogre::FrameEvent &evt);
	void	injectKeyDown(const OIS::KeyEvent& evt);
	void	injectKeyUp(const OIS::KeyEvent& evt);
	void	injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
	void	injectMouseUp(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
	
	void	deleteAvoidCollisonObject();

	void	addAlignedBox(SpiritCollision box)
	{

		if (!box.AABB.isNull())
		{
			m_vAxisaligneboxList.push_back(box);	
		}else
		{
			box.AABB = Ogre::AxisAlignedBox(0, 0, 0, 0, 0,0);
			box.NodeName = "SpiritCollisionName" + Ogre::StringConverter::toString(m_nCount);
			m_vAxisaligneboxList.push_back(box);
		}
		
	}
	size_t	getControlModel() // control model 0 key , 1 mouse
	{
		return m_fControlModel;
	}

	size_t	setControlModel(size_t model) // control model 0 key , 1 mouse
	{
		m_fControlModel = model;
	}

	

	//////////////////////////////////////////////////////////////////////////

	Vector3	getPosition()
	{
		return m_vEntityCurrentPos;
	}

	SceneNode*	getCollisionNode()
	{
		return m_pBodyNodeCollision;
	}

	float	getAttack()
	{
		return m_fAttack;
	}

	void PushAvoidColliSionName(std::string name)
	{
		m_vAvoidColliSionName.push_back(name);
	}
	void setControlModel(int mode)
	{
		m_fControlModel = mode;
	}

	void setPos(Vector3& pos)
	{
		m_vInitPos = pos;
	}
};
#endif